1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.lang3.builder;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNull;
22 import org.junit.Test;
23
24
25
26
27
28
29 public class HashCodeBuilderTest {
30
31
32
33
34 static class ReflectionTestCycleA {
35 ReflectionTestCycleB b;
36
37 @Override
38 public int hashCode() {
39 return HashCodeBuilder.reflectionHashCode(this);
40 }
41 }
42
43
44
45
46 static class ReflectionTestCycleB {
47 ReflectionTestCycleA a;
48
49 @Override
50 public int hashCode() {
51 return HashCodeBuilder.reflectionHashCode(this);
52 }
53 }
54
55
56
57 @Test(expected=IllegalArgumentException.class)
58 public void testConstructorExZero() {
59 new HashCodeBuilder(0, 0);
60 }
61
62 @Test(expected=IllegalArgumentException.class)
63 public void testConstructorExEvenFirst() {
64 new HashCodeBuilder(2, 3);
65 }
66
67 @Test(expected=IllegalArgumentException.class)
68 public void testConstructorExEvenSecond() {
69 new HashCodeBuilder(3, 2);
70 }
71
72 @Test(expected=IllegalArgumentException.class)
73 public void testConstructorExEvenNegative() {
74 new HashCodeBuilder(-2, -2);
75 }
76
77 static class TestObject {
78 private int a;
79
80 public TestObject(final int a) {
81 this.a = a;
82 }
83
84 @Override
85 public boolean equals(final Object o) {
86 if (o == this) {
87 return true;
88 }
89 if (!(o instanceof TestObject)) {
90 return false;
91 }
92 final TestObject rhs = (TestObject) o;
93 return a == rhs.a;
94 }
95
96 @Override
97 public int hashCode() {
98 return a;
99 }
100
101 public void setA(final int a) {
102 this.a = a;
103 }
104
105 public int getA() {
106 return a;
107 }
108 }
109
110 static class TestSubObject extends TestObject {
111 private int b;
112
113 @SuppressWarnings("unused")
114 transient private int t;
115
116 public TestSubObject() {
117 super(0);
118 }
119
120 public TestSubObject(final int a, final int b, final int t) {
121 super(a);
122 this.b = b;
123 this.t = t;
124 }
125
126 @Override
127 public boolean equals(final Object o) {
128 if (o == this) {
129 return true;
130 }
131 if (!(o instanceof TestSubObject)) {
132 return false;
133 }
134 final TestSubObject rhs = (TestSubObject) o;
135 return super.equals(o) && b == rhs.b;
136 }
137
138 @Override
139 public int hashCode() {
140 return b*17 + super.hashCode();
141 }
142
143 }
144
145 @Test
146 public void testReflectionHashCode() {
147 assertEquals(17 * 37, HashCodeBuilder.reflectionHashCode(new TestObject(0)));
148 assertEquals(17 * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestObject(123456)));
149 }
150
151 @Test
152 public void testReflectionHierarchyHashCode() {
153 assertEquals(17 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0)));
154 assertEquals(17 * 37 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0), true));
155 assertEquals((17 * 37 + 7890) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(123456, 7890,
156 0)));
157 assertEquals(((17 * 37 + 7890) * 37 + 0) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(
158 123456, 7890, 0), true));
159 }
160
161 @Test(expected=IllegalArgumentException.class)
162 public void testReflectionHierarchyHashCodeEx1() {
163 HashCodeBuilder.reflectionHashCode(0, 0, new TestSubObject(0, 0, 0), true);
164 }
165
166 @Test(expected=IllegalArgumentException.class)
167 public void testReflectionHierarchyHashCodeEx2() {
168 HashCodeBuilder.reflectionHashCode(2, 2, new TestSubObject(0, 0, 0), true);
169 }
170
171 @Test(expected=IllegalArgumentException.class)
172 public void testReflectionHashCodeEx1() {
173 HashCodeBuilder.reflectionHashCode(0, 0, new TestObject(0), true);
174 }
175
176 @Test(expected=IllegalArgumentException.class)
177 public void testReflectionHashCodeEx2() {
178 HashCodeBuilder.reflectionHashCode(2, 2, new TestObject(0), true);
179 }
180
181 @Test(expected=IllegalArgumentException.class)
182 public void testReflectionHashCodeEx3() {
183 HashCodeBuilder.reflectionHashCode(13, 19, null, true);
184 }
185
186 @Test
187 public void testSuper() {
188 final Object obj = new Object();
189 assertEquals(17 * 37 + 19 * 41 + obj.hashCode(), new HashCodeBuilder(17, 37).appendSuper(
190 new HashCodeBuilder(19, 41).append(obj).toHashCode()).toHashCode());
191 }
192
193 @Test
194 public void testObject() {
195 Object obj = null;
196 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
197 obj = new Object();
198 assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).toHashCode());
199 }
200
201 @Test
202 public void testObjectBuild() {
203 Object obj = null;
204 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).build().intValue());
205 obj = new Object();
206 assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).build().intValue());
207 }
208
209 @Test
210 @SuppressWarnings("cast")
211 public void testLong() {
212 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((long) 0L).toHashCode());
213 assertEquals(17 * 37 + (int) (123456789L ^ 123456789L >> 32), new HashCodeBuilder(17, 37).append(
214 (long) 123456789L).toHashCode());
215 }
216
217 @Test
218 @SuppressWarnings("cast")
219 public void testInt() {
220 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((int) 0).toHashCode());
221 assertEquals(17 * 37 + 123456, new HashCodeBuilder(17, 37).append((int) 123456).toHashCode());
222 }
223
224 @Test
225 public void testShort() {
226 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short) 0).toHashCode());
227 assertEquals(17 * 37 + 12345, new HashCodeBuilder(17, 37).append((short) 12345).toHashCode());
228 }
229
230 @Test
231 public void testChar() {
232 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char) 0).toHashCode());
233 assertEquals(17 * 37 + 1234, new HashCodeBuilder(17, 37).append((char) 1234).toHashCode());
234 }
235
236 @Test
237 public void testByte() {
238 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte) 0).toHashCode());
239 assertEquals(17 * 37 + 123, new HashCodeBuilder(17, 37).append((byte) 123).toHashCode());
240 }
241
242 @Test
243 @SuppressWarnings("cast")
244 public void testDouble() {
245 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((double) 0d).toHashCode());
246 final double d = 1234567.89;
247 final long l = Double.doubleToLongBits(d);
248 assertEquals(17 * 37 + (int) (l ^ l >> 32), new HashCodeBuilder(17, 37).append(d).toHashCode());
249 }
250
251 @Test
252 @SuppressWarnings("cast")
253 public void testFloat() {
254 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((float) 0f).toHashCode());
255 final float f = 1234.89f;
256 final int i = Float.floatToIntBits(f);
257 assertEquals(17 * 37 + i, new HashCodeBuilder(17, 37).append(f).toHashCode());
258 }
259
260 @Test
261 public void testBoolean() {
262 assertEquals(17 * 37 + 0, new HashCodeBuilder(17, 37).append(true).toHashCode());
263 assertEquals(17 * 37 + 1, new HashCodeBuilder(17, 37).append(false).toHashCode());
264 }
265
266 @Test
267 public void testObjectArray() {
268 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((Object[]) null).toHashCode());
269 final Object[] obj = new Object[2];
270 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
271 obj[0] = new Object();
272 assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
273 obj[1] = new Object();
274 assertEquals((17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append(obj)
275 .toHashCode());
276 }
277
278 @Test
279 public void testObjectArrayAsObject() {
280 final Object[] obj = new Object[2];
281 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
282 obj[0] = new Object();
283 assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
284 obj[1] = new Object();
285 assertEquals((17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append(
286 (Object) obj).toHashCode());
287 }
288
289 @Test
290 public void testLongArray() {
291 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((long[]) null).toHashCode());
292 final long[] obj = new long[2];
293 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
294 obj[0] = 5L;
295 final int h1 = (int) (5L ^ 5L >> 32);
296 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
297 obj[1] = 6L;
298 final int h2 = (int) (6L ^ 6L >> 32);
299 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
300 }
301
302 @Test
303 public void testLongArrayAsObject() {
304 final long[] obj = new long[2];
305 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
306 obj[0] = 5L;
307 final int h1 = (int) (5L ^ 5L >> 32);
308 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
309 obj[1] = 6L;
310 final int h2 = (int) (6L ^ 6L >> 32);
311 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
312 }
313
314 @Test
315 public void testIntArray() {
316 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((int[]) null).toHashCode());
317 final int[] obj = new int[2];
318 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
319 obj[0] = 5;
320 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
321 obj[1] = 6;
322 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
323 }
324
325 @Test
326 public void testIntArrayAsObject() {
327 final int[] obj = new int[2];
328 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
329 obj[0] = 5;
330 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
331 obj[1] = 6;
332 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
333 }
334
335 @Test
336 public void testShortArray() {
337 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short[]) null).toHashCode());
338 final short[] obj = new short[2];
339 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
340 obj[0] = (short) 5;
341 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
342 obj[1] = (short) 6;
343 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
344 }
345
346 @Test
347 public void testShortArrayAsObject() {
348 final short[] obj = new short[2];
349 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
350 obj[0] = (short) 5;
351 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
352 obj[1] = (short) 6;
353 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
354 }
355
356 @Test
357 public void testCharArray() {
358 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char[]) null).toHashCode());
359 final char[] obj = new char[2];
360 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
361 obj[0] = (char) 5;
362 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
363 obj[1] = (char) 6;
364 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
365 }
366
367 @Test
368 public void testCharArrayAsObject() {
369 final char[] obj = new char[2];
370 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
371 obj[0] = (char) 5;
372 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
373 obj[1] = (char) 6;
374 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
375 }
376
377 @Test
378 public void testByteArray() {
379 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte[]) null).toHashCode());
380 final byte[] obj = new byte[2];
381 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
382 obj[0] = (byte) 5;
383 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
384 obj[1] = (byte) 6;
385 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
386 }
387
388 @Test
389 public void testByteArrayAsObject() {
390 final byte[] obj = new byte[2];
391 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
392 obj[0] = (byte) 5;
393 assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
394 obj[1] = (byte) 6;
395 assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
396 }
397
398 @Test
399 public void testDoubleArray() {
400 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((double[]) null).toHashCode());
401 final double[] obj = new double[2];
402 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
403 obj[0] = 5.4d;
404 final long l1 = Double.doubleToLongBits(5.4d);
405 final int h1 = (int) (l1 ^ l1 >> 32);
406 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
407 obj[1] = 6.3d;
408 final long l2 = Double.doubleToLongBits(6.3d);
409 final int h2 = (int) (l2 ^ l2 >> 32);
410 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
411 }
412
413 @Test
414 public void testDoubleArrayAsObject() {
415 final double[] obj = new double[2];
416 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
417 obj[0] = 5.4d;
418 final long l1 = Double.doubleToLongBits(5.4d);
419 final int h1 = (int) (l1 ^ l1 >> 32);
420 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
421 obj[1] = 6.3d;
422 final long l2 = Double.doubleToLongBits(6.3d);
423 final int h2 = (int) (l2 ^ l2 >> 32);
424 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
425 }
426
427 @Test
428 public void testFloatArray() {
429 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((float[]) null).toHashCode());
430 final float[] obj = new float[2];
431 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
432 obj[0] = 5.4f;
433 final int h1 = Float.floatToIntBits(5.4f);
434 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
435 obj[1] = 6.3f;
436 final int h2 = Float.floatToIntBits(6.3f);
437 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
438 }
439
440 @Test
441 public void testFloatArrayAsObject() {
442 final float[] obj = new float[2];
443 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
444 obj[0] = 5.4f;
445 final int h1 = Float.floatToIntBits(5.4f);
446 assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
447 obj[1] = 6.3f;
448 final int h2 = Float.floatToIntBits(6.3f);
449 assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
450 }
451
452 @Test
453 public void testBooleanArray() {
454 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((boolean[]) null).toHashCode());
455 final boolean[] obj = new boolean[2];
456 assertEquals((17 * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
457 obj[0] = true;
458 assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
459 obj[1] = false;
460 assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
461 }
462
463 @Test
464 public void testBooleanArrayAsObject() {
465 final boolean[] obj = new boolean[2];
466 assertEquals((17 * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
467 obj[0] = true;
468 assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
469 obj[1] = false;
470 assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
471 }
472
473 @Test
474 public void testBooleanMultiArray() {
475 final boolean[][] obj = new boolean[2][];
476 assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
477 obj[0] = new boolean[0];
478 assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
479 obj[0] = new boolean[1];
480 assertEquals((17 * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
481 obj[0] = new boolean[2];
482 assertEquals(((17 * 37 + 1) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
483 obj[0][0] = true;
484 assertEquals(((17 * 37 + 0) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
485 obj[1] = new boolean[1];
486 assertEquals(((17 * 37 + 0) * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
487 }
488
489 @Test
490 public void testReflectionHashCodeExcludeFields() throws Exception {
491 final TestObjectWithMultipleFields x = new TestObjectWithMultipleFields(1, 2, 3);
492
493 assertEquals(((17 * 37 + 1) * 37 + 2) * 37 + 3, HashCodeBuilder.reflectionHashCode(x));
494
495 assertEquals(((17 * 37 + 1) * 37 + 2) * 37 + 3, HashCodeBuilder.reflectionHashCode(x, (String[]) null));
496 assertEquals(((17 * 37 + 1) * 37 + 2) * 37 + 3, HashCodeBuilder.reflectionHashCode(x, new String[]{}));
497 assertEquals(((17 * 37 + 1) * 37 + 2) * 37 + 3, HashCodeBuilder.reflectionHashCode(x, new String[]{"xxx"}));
498
499 assertEquals((17 * 37 + 1) * 37 + 3, HashCodeBuilder.reflectionHashCode(x, new String[]{"two"}));
500 assertEquals((17 * 37 + 1) * 37 + 2, HashCodeBuilder.reflectionHashCode(x, new String[]{"three"}));
501
502 assertEquals(17 * 37 + 1, HashCodeBuilder.reflectionHashCode(x, new String[]{"two", "three"}));
503
504 assertEquals(17, HashCodeBuilder.reflectionHashCode(x, new String[]{"one", "two", "three"}));
505 assertEquals(17, HashCodeBuilder.reflectionHashCode(x, new String[]{"one", "two", "three", "xxx"}));
506 }
507
508 static class TestObjectWithMultipleFields {
509 @SuppressWarnings("unused")
510 private int one = 0;
511
512 @SuppressWarnings("unused")
513 private int two = 0;
514
515 @SuppressWarnings("unused")
516 private int three = 0;
517
518 public TestObjectWithMultipleFields(final int one, final int two, final int three) {
519 this.one = one;
520 this.two = two;
521 this.three = three;
522 }
523 }
524
525
526
527
528 @Test
529 public void testReflectionObjectCycle() {
530 final ReflectionTestCycleA a = new ReflectionTestCycleA();
531 final ReflectionTestCycleB b = new ReflectionTestCycleB();
532 a.b = b;
533 b.a = a;
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552 a.hashCode();
553 assertNull(HashCodeBuilder.getRegistry());
554 b.hashCode();
555 assertNull(HashCodeBuilder.getRegistry());
556 }
557
558
559
560
561 @Test
562 public void testToHashCodeEqualsHashCode() {
563 final HashCodeBuilder hcb = new HashCodeBuilder(17, 37).append(new Object()).append('a');
564 assertEquals("hashCode() is no longer returning the same value as toHashCode() - see LANG-520",
565 hcb.toHashCode(), hcb.hashCode());
566 }
567
568 }